//
//  SLWebView.m
//  SLWebView
//
//  Created by S_LINE on 2020/6/23.
//  Copyright © 2020 S_LINE. All rights reserved.
//

#import "SLWebView.h"

#import "WKWebViewConfiguration+SLWebView.h"

@interface SLWebView ()<WKNavigationDelegate, WKUIDelegate>

@end

@implementation SLWebView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupViewWithConfiguration:nil];
    }
    return self;
}

- (instancetype)initWithConfiguration:(WKWebViewConfiguration *)configuration {
    if (self = [super init]) {
        [self setupViewWithConfiguration:configuration];
    }
    return self;
}

- (void)setupViewWithConfiguration:(WKWebViewConfiguration *)configuration {
    if (configuration == nil) {
        configuration = [WKWebViewConfiguration slWebViewConfiguration];
    }
    if (self.wkWebView) {
        [self.wkWebView removeFromSuperview];
        self.wkWebView = nil;
    }
    self.wkWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height) configuration:configuration];
    [self addSubview:self.wkWebView];
    self.wkWebView.navigationDelegate = self;
    self.wkWebView.UIDelegate = self;
    self.wkWebView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    
}

#pragma mark Receive Massege From JS
#pragma mark HandlerDelegate
//-(void)handleScriptMessage{
//    __weak typeof(self) weakSelf = self;
//    [self registerNativeMethod:@"CallNative" handle:^(id  _Nullable data, CallJSResponseCallback  _Nullable responseCallback) {
//        @strongify(self)
//        [weakSelf handleMessage:data jsResponseCallBack:responseCallback];
//    }];
//}
//
//-(void)handleMessage:(id)message jsResponseCallBack:(CallJSResponseCallback)responseCallback{
//    if (message != nil)
//    {
//        if([self.delegate respondsToSelector:@selector(webView:didReceiveJSMessage:jsResponseCallBack:)]) {
//            [self.delegate webView:self didReceiveJSMessage:message jsResponseCallBack:responseCallback];
//        }
//    }
//}

#pragma mark - WKNavigationDelegate
/// 当Web视图开始接收Web内容时调用，参数1: 调用委托方法的Web视图，参数2:一个对象WKNavigation包含跟踪网页加载进度的信息
//- (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation;
/// 当Web内容开始在Web视图中加载时调用，这个方法在上一个方法之前
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
{
    
}

/// 决定是否允许或取消导航, 在发送请求之前，决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    WKNavigationActionPolicy policy = WKNavigationActionPolicyAllow;
    if (self.navigationDelegate &&
        [self.navigationDelegate respondsToSelector:@selector(webView:didStartLoadingURL:isLinkActivate:)]) {
        if (![self.navigationDelegate webView:self didStartLoadingURL:navigationAction.request.URL isLinkActivate:(navigationAction.navigationType == WKNavigationTypeLinkActivated)]) {
            policy = WKNavigationActionPolicyCancel;
        }
    }
    
    decisionHandler(policy);
}

//- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler;

/// 决定是否在其响应已知之后允许或取消导航，在收到响应后，决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
    for (NSHTTPCookie *cookie in cookies)
    {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }
    decisionHandler(WKNavigationResponsePolicyAllow);
}

/// 当Web视图接收服务器重定向时调用，主机地址被重定向时调用
//- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation;

/// 当Web视图加载内容时发生错误时调用，页面加载失败，没有网络，加载地址，进入的是这个回调
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error
{
    if (self.navigationDelegate && [self.navigationDelegate respondsToSelector:@selector(webView:didFailToLoadURL:error:)])
    {
        [self.navigationDelegate webView:self didFailToLoadURL:self.wkWebView.URL error:error];
    }
}

/// 跳转成功,页面加载完毕时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
{
    if (self.navigationDelegate && [self.navigationDelegate respondsToSelector:@selector(webView:didFinishLoadingURL:)])
    {
        [self.navigationDelegate webView:self didFinishLoadingURL:self.wkWebView.URL];
    }
}

/// 在导航过程中发生错误时调用，跳转失败时调用
- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error
{
    if (self.navigationDelegate && [self.navigationDelegate respondsToSelector:@selector(webView:didFailToLoadURL:error:)])
    {
        [self.navigationDelegate webView:self didFailToLoadURL:self.wkWebView.URL error:error];
    }
}

/// 当Web视图需要对认证挑战作出响应时调用，如果需要证书验证，与使用AFN进行HTTPS证书验证是一样的
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
{
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential, card);
    }
}

/// 当Web视图的Web内容处理终止时调用，9.0才能使用，web内容处理中断时会触发
//- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView;

#pragma mark - WKUIDelegate
- (nullable WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures {
    if (!navigationAction.targetFrame.isMainFrame) {
        [webView loadRequest:navigationAction.request];
    }
    return nil;
}

//- (void)webViewDidClose:(WKWebView *)webView;

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    if (self.UIDelegate && [self.UIDelegate respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:)])
    {
        [self.UIDelegate webView:self runJavaScriptAlertPanelWithMessage:message initiatedByFrame:frame completionHandler:completionHandler];
    }
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler
{
    if (self.UIDelegate && [self.UIDelegate respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:)])
    {
        [self.UIDelegate webView:self runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:frame completionHandler:completionHandler];
    }
}

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler
{
    if (self.UIDelegate && [self.UIDelegate respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:)])
    {
        [self.UIDelegate webView:self runJavaScriptTextInputPanelWithPrompt:prompt defaultText:defaultText initiatedByFrame:frame completionHandler:completionHandler];
    }
}

//- (BOOL)webView:(WKWebView *)webView shouldPreviewElement:(WKPreviewElementInfo *)elementInfo API_DEPRECATED_WITH_REPLACEMENT("webView:contextMenuConfigurationForElement:completionHandler:", ios(10.0, 13.0));
//
//- (nullable UIViewController *)webView:(WKWebView *)webView previewingViewControllerForElement:(WKPreviewElementInfo *)elementInfo defaultActions:(NSArray<id <WKPreviewActionItem>> *)previewActions API_DEPRECATED_WITH_REPLACEMENT("webView:contextMenuConfigurationForElement:completionHandler:", ios(10.0, 13.0));
//
//- (void)webView:(WKWebView *)webView commitPreviewingViewController:(UIViewController *)previewingViewController API_DEPRECATED_WITH_REPLACEMENT("webView:contextMenuForElement:willCommitWithAnimator:", ios(10.0, 13.0));
//
//- (void)webView:(WKWebView *)webView contextMenuConfigurationForElement:(WKContextMenuElementInfo *)elementInfo completionHandler:(void (^)(UIContextMenuConfiguration * _Nullable configuration))completionHandler API_AVAILABLE(ios(13.0));
//
//- (void)webView:(WKWebView *)webView contextMenuWillPresentForElement:(WKContextMenuElementInfo *)elementInfo API_AVAILABLE(ios(13.0));
//
//- (void)webView:(WKWebView *)webView contextMenuForElement:(WKContextMenuElementInfo *)elementInfo willCommitWithAnimator:(id <UIContextMenuInteractionCommitAnimating>)animator API_AVAILABLE(ios(13.0));
//
//- (void)webView:(WKWebView *)webView contextMenuDidEndForElement:(WKContextMenuElementInfo *)elementInfo API_AVAILABLE(ios(13.0));
//
//- (void)webView:(WKWebView *)webView runOpenPanelWithParameters:(WKOpenPanelParameters *)parameters initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSArray<NSURL *> * _Nullable URLs))completionHandler API_AVAILABLE(macos(10.12));

#pragma mark - public
- (void)loadRequest:(NSURLRequest *)request
{
    if (self.wkWebView)
    {
        [self.wkWebView loadRequest:request];
    }
}

- (void)loadURL:(NSURL *)URL
{
    [self loadRequest:[NSURLRequest requestWithURL:URL]];
}

- (void)loadURLString:(NSString *)URLString
{
    NSURL *URL = [NSURL URLWithString:URLString];
    [self loadURL:URL];
}

- (void)loadHTMLString:(NSString *)HTMLString
{
    if (self.wkWebView)
    {
        [self.wkWebView loadHTMLString:HTMLString baseURL:nil];
    }
}

- (void)reload
{
    if (self.wkWebView)
    {
        [self.wkWebView reload];
    }
}

- (BOOL)back
{
    if (self.wkWebView)
    {
        if ([self.wkWebView canGoBack])
        {
            [self.wkWebView goBack];
            return YES;
        }
        return NO;
    }
    return NO;
}

- (void)stopLoad
{
    if (self.wkWebView)
    {
        [self.wkWebView stopLoading];
    }
}

@end
